home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Scene Storm
/
Scene Storm - Volume 1.iso
/
coding
/
c
/
nullmodem
/
src
/
device.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-12-18
|
9KB
|
322 lines
#include "defs.h"
#include "protos.h"
extern char DeviceName[];
extern UBYTE S_Default[];
struct TagItem ModemProcTagList[] = {
{ NP_Entry, modem_task },
{ NP_Name, DeviceName },
{ NP_Priority, MODEM_TASK_PRI },
{ NP_StackSize, MODEM_STACK_SIZE},
{ TAG_DONE, TAG_DONE },
};
/*
* Creates and Initialises a Modem
*/
struct NullModem *CreateModem(ULONG modemnum)
{
struct NullModem *modem;
if( modem = AllocMem(sizeof(struct NullModem), MEMF_PUBLIC | MEMF_CLEAR) ) {
if( modem->nm_Unit[0] = AllocMem(sizeof(struct NullUnit), MEMF_PUBLIC | MEMF_CLEAR) ) {
if( modem->nm_Unit[1] = AllocMem(sizeof(struct NullUnit), MEMF_PUBLIC | MEMF_CLEAR) ) {
if( OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)&modem->nm_Timerequest, 0) == 0 ) {
struct Library *DOSBase;
if( DOSBase = OpenLibrary("dos.library",36) ) {
struct Process *pr = CreateNewProc(ModemProcTagList);
CloseLibrary(DOSBase);
if( pr ) {
int i;
for( i = 0 ; i < 2 ; i++ ) {
struct NullUnit *unit = modem->nm_Unit[i];
int j;
unit->u_Readptr = unit->u_Buffer;
NewList((struct List *)&unit->u_Readlist);
unit->u_Writeptr = unit->u_Buffer;
NewList((struct List *)&unit->u_Writelist);
unit->u_Unitnum = i;
unit->u_Modem = modem;
for( j = 0 ; j < 64 ; j++ )
unit->u_SReg[j] = S_Default[j];
}
pr->pr_Task.tc_UserData = modem; /* So the modem Process can find its data */
modem->nm_Taskptr = &pr->pr_Task; /* and so everybody else knows where to signal */
InitSemaphore(&modem->nm_Semaphore);
modem->nm_Modemnum = modemnum;
DevBase->b_Modem[modemnum] = modem;
DevBase->b_Lib.lib_OpenCnt++; /* hold the device for the task */
return(modem); /* gotit */
}
}
CloseDevice( (struct IORequest *)&modem->nm_Timerequest );
}
FreeMem(modem->nm_Unit[1], sizeof(struct NullUnit));
}
FreeMem(modem->nm_Unit[0], sizeof(struct NullUnit));
}
FreeMem(modem, sizeof(struct NullModem));
}
return(NULL);
}
/*
* open device (in a Forbid)
*
* unitnum: D0
* flags: D1
* iob: A1
*
*/
struct NullBase *
DevOpen( __D0 ULONG unitnum,
__D1 ULONG flags,
__A1 struct IOExtSer *iob)
{
struct NullBase *db = DevBase;
ULONG modemnum = unitnum >> 1;
db->b_Lib.lib_OpenCnt++; /* fake opener so we don't get expunged */
/*
* set fail conditions as default..
*/
iob->IOSer.io_Error = IOERR_OPENFAIL;
iob->IOSer.io_Device = (struct Device *)-1; /* trashed */
/*
* range check
*/
if( modemnum < MODEM_UNITS ) {
struct NullModem *modem = db->b_Modem[modemnum];
if( modem || (modem = CreateModem(modemnum)) ) {
struct NullUnit *unit = modem->nm_Unit[unitnum & 1];
if( (unit->u_OpenCnt == 0) || (unit->u_Flags & SERF_SHARED & iob->io_SerFlags) ) {
/* open the unit */
if( unit->u_OpenCnt++ == 0 ) {
unit->u_Flags = iob->io_SerFlags & SERF_SHARED;
unit->u_SReg[SREG_STATE] = STATE_COMMAND;
unit->u_SReg[SREG_CMD_COUNT] = 0;
}
/* open the modem */
modem->nm_OpenCnt++;
/* open the device */
db->b_Lib.lib_OpenCnt++;
/* tell them all about it */
iob->IOSer.io_Device = (struct Device *)db; /* restored */
iob->IOSer.io_Unit = unit;
iob->IOSer.io_Error = 0;
iob->IOSer.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
/* prefs? pah ;-) */
iob->io_CtlChar = SER_DEFAULT_CTLCHAR;
iob->io_RBufLen = UNIT_BUF_SIZE;
iob->io_Baud = 9600;
dprintf(unit, 2, "OpenDevice\n");
}
}
}
db->b_Lib.lib_OpenCnt--; /* end of fake opener */
return(iob->IOSer.io_Error);
}
/*
* close device (in a Forbid)
*
* iob: A1
*
* returns the Segment pointer if the device is to be unloaded, NULL
* otherwise -- we always return NULL, because the task takes care of
* its own cleanup, and we can't unload until then
*/
APTR
DevClose(__A1 struct IOExtSer *iob)
{
struct NullBase *db = DevBase;
struct NullUnit *unit = (struct NullUnit *)iob->IOSer.io_Unit;
struct NullModem *modem = unit->u_Modem;
/*
* make sure we don't take anything with this iob again
*/
iob->IOSer.io_Unit = (struct Unit *)-1;
iob->IOSer.io_Device = (struct Device *)-1;
dprintf(unit,2,"CloseDevice\n");
unit->u_OpenCnt--;
modem->nm_OpenCnt--;
db->b_Lib.lib_OpenCnt--;
/*
* DTR hangup if the unit is empty
*/
if( unit->u_OpenCnt == 0 ) {
dprintf(unit,3,"DTR drop signalled\n");
Signal(modem->nm_Taskptr, SIGBREAKF_CTRL_D);
}
/*
* and Zap the modem if nobody is left
*/
if( modem->nm_OpenCnt == 0 ) {
dprintf(unit,3,"Task Exit signal sent\n");
Signal(modem->nm_Taskptr, SIGBREAKF_CTRL_E);
db->b_Modem[modem->nm_Modemnum] = NULL;
}
return(NULL);
}
/*
* device Expunge (in a Forbid)
*
* no arguments
*
* returns segment passed to Init if we want to expunge, NULL otherwise
*
*/
APTR
DevExpunge(void)
{
struct NullBase *db = DevBase;
APTR dseg = db->b_Segment;
/*
* but not yet if we are still open!
*/
if( db->b_Lib.lib_OpenCnt ) {
return(NULL);
}
/*
* bye bye
*/
Remove( &db->b_Lib.lib_Node );
FreeMem((UBYTE *)db - db->b_Lib.lib_NegSize, db->b_Lib.lib_NegSize + db->b_Lib.lib_PosSize);
return(dseg);
}
/*
* device Reserved no arguments, return NULL
* (reserved for future use by C=)
*
*/
ULONG
DevReserved(void)
{
return(NULL);
}
/*
* device BeginIO
*
* iob: a1
*
*/
void
DevBeginIO(__A1 struct IOExtSer *iob)
{
struct NullUnit *unit = (struct NullUnit *)iob->IOSer.io_Unit;
static struct IOExtSer *(*cmd_table[])(struct IOExtSer *) = {
cmd_invalid,
cmd_reset,
cmd_read,
cmd_write,
cmd_update,
cmd_clear,
cmd_stop,
cmd_start,
cmd_flush,
sdcmd_query,
sdcmd_break,
sdcmd_setparams,
cmd_invalid,
cmd_invalid,
cmd_invalid,
cmd_invalid,
asdg_dtrcontrol,
};
dprintf(unit, 3, "BeginIO (Cmd #%ld)\n",iob->IOSer.io_Command);
iob->IOSer.io_Message.mn_Node.ln_Type = NT_MESSAGE;
if( iob->IOSer.io_Command >= arraysize(cmd_table) ) {
iob->IOSer.io_Error = IOERR_NOCMD;
}
else {
iob->IOSer.io_Error = 0;
iob->IOSer.io_Actual = 0;
iob = (*cmd_table[iob->IOSer.io_Command])(iob); /* do the command */
}
if( iob ) /* read & write return NULL if the request was queued */
if( (iob->IOSer.io_Flags & IOF_QUICK) == 0 )
ReplyMsg(&iob->IOSer.io_Message);
}
/*
* device AbortIO
*
* iob: a1
*
*/
ULONG
DevAbortIO(__A1 struct IOExtSer *iob)
{
struct NullUnit *unit = (struct NullUnit *)iob->IOSer.io_Unit;
ObtainSemaphore(&unit->u_Modem->nm_Semaphore);
/* we only abort if the message hasn't been done already.. */
/* it could have completed while we were waiting for the Semaphore */
if( iob->IOSer.io_Message.mn_Node.ln_Type != NT_REPLYMSG && (iob->IOSer.io_Flags & IOF_QUICK) == 0 ) {
Remove(&iob->IOSer.io_Message.mn_Node);
iob->IOSer.io_Error = IOERR_ABORTED;
ReplyMsg(&iob->IOSer.io_Message);
dprintf(unit, 1,"AbortIO (aborted)\n");
}
else {
dprintf(unit, 1,"AbortIO (already complete)\n");
}
ReleaseSemaphore(&unit->u_Modem->nm_Semaphore);
return(iob->IOSer.io_Error);
}